<?php

namespace App\Model\Common;

use App\Model\CrudModel;
use App\Pool\Redis\DefaultPool;
use Hyperf\Di\Annotation\Inject;

/**
 * @property int $id
 * @property int $pid
 * @property int $sort
 * @property string $input_type
 * @property string $name
 * @property string $code
 * @property string $val
 */
class SettingModel extends CrudModel
{
    // 配置
    protected ?string $table = 'setting';

    protected string $cacheKeyPrefix = '_set_';
    
    protected array $adminPageListField = [
        'id','code','name','pid','sort','input_type','val','ext',
    ];

    #[Inject]
    protected DefaultPool $redis;
    
    protected array $casts = [
        'ext' => 'array'
    ];

    public function addOne(array $data)
    {
        $add = [
            'name' => trim($data['name']),
            'code' => trim($data['code']),
            'pid' => intval($data['pid']),
            'sort' => intval($data['sort']),
            'input_type' => trim($data['input_type']),
            'val' => trim($data['val']),
            'ext' => json_encode($data['ext'] ?? [])
        ];
        return $this->normalAddOne($add);
    }

    public function updateById($id, array $data)
    {
        return $this->buildQuery(['id'=>$id,])->update([
            'pid' => intval($data['pid']),
            'sort' => intval($data['sort']),
            'input_type' => trim($data['input_type']),
            'val' => trim($data['val']),
            'ext' => json_encode($data['ext'] ?? []),
            'updated_at' => time(),
        ]);
    }

    public function updateVal($id, $val)
    {
        return $this->updateField(['id'=>$id,],'val',$val);
    }

    /**
     * @param $code
     * @param $field
     * @return static
     */
    public function findByCode($code, $field=['*'])
    {
        return $this->buildQuery(['code'=> $code])->first($field);
    }

    /**
     * 从缓存中读取
     * @param string $code
     * @return false|string
     */
    public function findByCodeFromCache($code)
    {
        $key = $this->cacheKeyPrefix . $code;
        $cacheVal = $this->redis->get($key);
        if ($cacheVal !== false){
            return $cacheVal === 'none' ? null : $cacheVal;
        }
        // 从数据库读取
        $set = $this->findByCode($code,['code','val']);
        if (!$set){
            // 避免一直击穿数据库，ex结合实际情况设置
            $this->setCache($code,'none',['ex'=>600]);
            return null;
        }
        $this->setCache($set->code, $set->val);
        return $set->val;
    }

    /**
     * 写入缓存
     * @param string $code
     * @param string $val
     * @param mixed $timeout 传递给redis->set()的第三个参数
     */
    public function setCache($code, $val, $timeout=null)
    {
        $key = $this->cacheKeyPrefix . $code;
        return $this->redis->set($key, $val, $timeout);
    }

    /**
     * 删除多个缓存
     * @param array $codes
     * @return false|int
     */
    public function delSomeCacheByCodes(array $codes)
    {
        return $this->redis->del($codes);
    }

    protected function pageListSort($builder)
    {
        return $builder->orderByDesc('sort');
    }
}